#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import logging
from typing import Dict, List, Optional, Any

from repository import (
    ParkingSpotRepository,
    ReservationRepository,
    VehicleRecordRepository,
    IncomeRepository,
    PricingRuleRepository,
    PlateDetectionRepository
)

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class ParkingService:
    """停车服务"""
    
    @staticmethod
    def get_parking_spots():
        """获取所有车位信息"""
        # 获取基本车位信息
        spots = ParkingSpotRepository.get_parking_spots()
        logger.info(f"获取到 {len(spots)} 个车位信息")
        
        # 获取当前时间戳，用于计算实时费用
        current_time = int(time.time() * 1000)
        
        # 获取所有活跃的车辆记录，用于匹配车位
        active_records = VehicleRecordRepository.get_vehicle_records()
        active_records = [r for r in active_records if r["status"] != "exited" and r["exit_time"] is None]
        logger.info(f"获取到 {len(active_records)} 条活跃车辆记录")
        
        # 记录所有活跃记录的车位号，用于排查问题
        active_spots = {r["spot_number"]: r["plate_number"] for r in active_records}
        logger.info(f"当前活跃车位占用情况: {active_spots}")
        
        # 为占用状态的车位添加车牌号和实时计费信息
        for spot in spots:
            # 记录原始状态，方便排查问题
            original_status = spot["status"]
            spot_number = spot["spot_number"]
            logger.info(f"处理车位 {spot_number}, 原始状态: {original_status}")
            
            # 查找占用该车位的活跃车辆记录
            vehicle_record = None
            for record in active_records:
                if record["spot_number"] == spot_number:
                    vehicle_record = record
                    break
            
            # 如果有活跃车辆记录，则更新车位状态并添加车辆信息
            if vehicle_record:
                logger.info(f"车位 {spot_number} 找到活跃记录: 车牌={vehicle_record['plate_number']}")
                
                # 如果数据库状态不一致，强制更新为occupied
                if spot["status"] != "occupied":
                    logger.warning(f"数据不一致：车位 {spot_number} 有活跃车辆记录但状态为 {spot['status']}，强制更新为occupied")
                    ParkingSpotRepository.update_parking_spot_status(spot_number, "occupied", current_time)
                    spot["status"] = "occupied"
                
                # 添加车牌号信息
                spot["plate_number"] = vehicle_record["plate_number"]
                
                # 计算实时费用
                entry_time = vehicle_record["entry_time"]
                current_fee = PricingService.calculate_fee(entry_time, current_time)
                
                # 添加费用和停车时长信息
                spot["current_fee"] = current_fee
                spot["parking_duration"] = current_time - entry_time  # 毫秒
                spot["entry_time"] = entry_time
                
                logger.info(f"车位 {spot_number} 状态更新为: 占用, 车牌={spot['plate_number']}, 费用={current_fee}")
            else:
                # 如果没有活跃记录，但状态为occupied，修正为free
                if spot["status"] == "occupied":
                    logger.warning(f"数据不一致：车位 {spot_number} 状态为occupied但无活跃车辆记录，强制更新为free")
                    ParkingSpotRepository.update_parking_spot_status(spot_number, "free", current_time)
                    spot["status"] = "free"
                
                # 空闲车位不需要计费信息
                spot["plate_number"] = None
                spot["current_fee"] = 0
                spot["parking_duration"] = 0
                spot["entry_time"] = None
                
                logger.info(f"车位 {spot_number} 状态确认为: 空闲")
        
        # 最后再次检查更新是否成功
        for spot in spots:
            logger.info(f"最终车位状态: {spot['spot_number']} = {spot['status']}, 车牌 = {spot['plate_number']}")
                
        return spots
    
    @staticmethod
    def get_parking_spot(spot_id: int):
        """获取特定车位信息"""
        return ParkingSpotRepository.get_parking_spot(spot_id)
    
    @staticmethod
    def get_parking_spot_by_number(spot_number: str):
        """根据车位号获取特定车位信息"""
        logger.info(f"正在查询车位号: {spot_number}")
        spots = ParkingSpotRepository.get_parking_spots()
        logger.info(f"获取到 {len(spots)} 个车位信息")
        
        for spot in spots:
            if spot["spot_number"] == spot_number:
                logger.info(f"找到匹配车位: {spot}")
                return spot
        
        logger.warning(f"未找到匹配车位: {spot_number}")
        return None
    
    @staticmethod
    def get_parking_summary():
        """获取车位使用情况汇总"""
        return ParkingSpotRepository.get_parking_summary()
    
    @staticmethod
    def update_parking_spot_status(spot_number: str, is_occupied: bool):
        """根据传感器状态更新车位状态"""
        timestamp = int(time.time() * 1000)
        status = "occupied" if is_occupied else "free"
        return ParkingSpotRepository.update_parking_spot_status(spot_number, status, timestamp)
    
    @staticmethod
    def get_available_parking_spots():
        """获取所有可用（状态为free）的车位"""
        all_spots = ParkingSpotRepository.get_parking_spots()
        logger.info(f"获取到总车位数: {len(all_spots)}")
        
        available_spots = [spot for spot in all_spots if spot["status"] == "free"]
        logger.info(f"可用车位数: {len(available_spots)}")
        
        if available_spots:
            spot_numbers = [spot["spot_number"] for spot in available_spots]
            logger.info(f"可用车位号: {spot_numbers}")
        else:
            logger.warning("当前没有可用车位")
            
        return available_spots

class ReservationService:
    """预约服务"""
    
    @staticmethod
    def create_reservation(plate_number: str, spot_number: str, start_time: int, end_time: Optional[int] = None):
        """创建预约"""
        # 检查车位是否可用
        spot = ParkingService.get_parking_spot_by_number(spot_number)
        if not spot or spot["status"] != "free":
            return {"success": False, "message": "车位不可用或已被占用"}
        
        # 检查是否已有该车牌的活跃预约
        existing_reservation = ReservationRepository.get_active_reservation_by_plate(plate_number)
        if existing_reservation:
            return {"success": False, "message": "该车牌已有活跃预约"}
        
        # 创建预约
        reservation_id = ReservationRepository.create_reservation(plate_number, spot_number, start_time, end_time)
        if reservation_id:
            return {"success": True, "reservation_id": reservation_id}
        else:
            return {"success": False, "message": "创建预约失败"}
    
    @staticmethod
    def get_reservations(status: Optional[str] = None):
        """获取预约列表"""
        return ReservationRepository.get_reservations(status)
    
    @staticmethod
    def get_reservations_by_plate(plate_number: str):
        """根据车牌号获取预约列表"""
        return ReservationRepository.get_reservations_by_plate(plate_number)
    
    @staticmethod
    def get_reservation(reservation_id: int):
        """获取特定预约"""
        return ReservationRepository.get_reservation(reservation_id)
    
    @staticmethod
    def cancel_reservation(reservation_id: int):
        """取消预约"""
        reservation = ReservationRepository.get_reservation(reservation_id)
        if not reservation:
            return {"success": False, "message": "预约不存在"}
        
        # 只有待入场状态的预约可以被取消
        if reservation["status"] != "waiting_entry":
            return {"success": False, "message": "只有待入场的预约可以被取消"}
        
        result = ReservationRepository.update_reservation_status(reservation_id, "cancelled")
        if result:
            return {"success": True, "message": "预约已取消"}
        else:
            return {"success": False, "message": "取消预约失败"}

class VehicleService:
    """车辆服务"""
    
    @staticmethod
    def process_vehicle_entry(plate_number: str, spot_number: str):
        """处理车辆进入"""
        # 确保车牌号格式规范
        plate_number = plate_number.strip().upper() if plate_number else plate_number
        logger.info(f"处理车辆入场：车牌号={plate_number}, 车位号={spot_number}")
        
        timestamp = int(time.time() * 1000)
        
        # 先检查车辆是否已有活跃记录
        existing_record = VehicleRecordRepository.get_active_vehicle_record(plate_number)
        if existing_record:
            logger.warning(f"车辆已有活跃记录：{existing_record}")
            return {"success": False, "message": "该车辆已入场", "existing_record": existing_record}
        
        # 检查是否有预约
        reservation = ReservationRepository.get_active_reservation_by_plate(plate_number)
        logger.info(f"检查车辆预约: {reservation}")
        
        if reservation:
            if reservation["status"] == "waiting_entry":
                # 有待入场的预约，更新为已入场状态
                logger.info(f"车辆有待入场预约，更新预约状态为已入场: id={reservation['id']}")
                ReservationRepository.update_reservation_status(reservation["id"], "entered")
                status = "reserved_entry"
            elif reservation["status"] == "entered":
                # 预约已入场状态，记录重复入场
                logger.warning(f"车辆预约已处于入场状态: id={reservation['id']}")
                status = "duplicate_entry"
            else:
                # 其他状态，如已出场但未支付等情况
                logger.info(f"车辆预约状态为{reservation['status']}, 按普通方式入场")
                status = "direct_entry"
        else:
            # 无预约，直接进入
            logger.info(f"车辆无预约，直接入场")
            status = "direct_entry"
        
        try:
            # 创建车辆记录
            record_id = VehicleRecordRepository.create_vehicle_record(
                plate_number,
                spot_number,
                timestamp,
                status
            )
            logger.info(f"创建车辆记录成功: id={record_id}")
            
            # 明确更新车位状态为已占用
            logger.info(f"更新车位状态为已占用: spot_number={spot_number}")
            success = ParkingSpotRepository.update_parking_spot_status(spot_number, "occupied", timestamp)
            logger.info(f"更新车位状态结果: {success}")
            
            # 验证车位状态是否正确更新
            spot = ParkingService.get_parking_spot_by_number(spot_number)
            logger.info(f"更新后的车位状态: {spot}")
            
            if spot and spot["status"] == "occupied":
                logger.info(f"车位状态更新成功: {spot_number} 状态为 occupied")
            else:
                logger.error(f"车位状态更新失败: {spot_number} 当前状态为 {spot['status'] if spot else 'unknown'}")
                # 再次尝试更新
                ParkingSpotRepository.update_parking_spot_status(spot_number, "occupied", timestamp)
            
            return {
                "success": True,
                "record_id": record_id,
                "message": "车辆进入成功",
                "entry_type": status
            }
        except Exception as e:
            logger.error(f"处理车辆入场出错: {e}")
            logger.exception(e)
            return {"success": False, "message": f"处理车辆入场失败: {str(e)}"}
    
    @staticmethod
    def process_vehicle_exit(plate_number: str):
        """处理车辆离开"""
        timestamp = int(time.time() * 1000)
        
        # 查找活跃的车辆记录
        record = VehicleRecordRepository.get_active_vehicle_record(plate_number)
        if not record:
            return {"success": False, "message": "未找到该车辆的进入记录"}
        
        # 更新车辆记录
        VehicleRecordRepository.update_vehicle_record(record["id"], timestamp, "exited")
        
        # 更新车位状态
        ParkingSpotRepository.update_parking_spot_status(record["spot_number"], "free", timestamp)
        
        # 检查是否有活跃的预约
        reservation = ReservationRepository.get_active_reservation_by_plate(plate_number)
        
        if reservation:
            if reservation["status"] == "entered":
                # 更新预约状态为已出场并待支付
                logger.info(f"车辆有已入场预约，更新为已出场待支付状态: id={reservation['id']}")
                ReservationRepository.update_reservation_status(reservation["id"], "waiting_payment", timestamp)
                
                # 计算费用
                entry_time = record["entry_time"]
                exit_time = timestamp
                amount = PricingService.calculate_fee(entry_time, exit_time)
                
                # 创建收入记录
                income_id = IncomeRepository.create_income_record(
                    reservation["id"],
                    plate_number,
                    amount,
                    entry_time,
                    exit_time
                )
                
                return {
                    "success": True,
                    "message": "车辆离开成功，已生成待支付账单",
                    "amount": amount,
                    "income_id": income_id,
                    "reservation_id": reservation["id"],
                    "status": "waiting_payment"
                }
            else:
                # 其他状态，可能是未入场就出场或已出场
                logger.warning(f"车辆预约状态异常: {reservation['status']}")
        
        # 无预约或预约状态异常，直接计费
        entry_time = record["entry_time"]
        exit_time = timestamp
        amount = PricingService.calculate_fee(entry_time, exit_time)
        
        # 创建收入记录
        income_id = IncomeRepository.create_income_record(
            0,  # 无预约
            plate_number,
            amount,
            entry_time,
            exit_time
        )
        
        return {
            "success": True,
            "message": "车辆离开成功，已生成账单",
            "amount": amount,
            "income_id": income_id
        }
    
    @staticmethod
    def get_vehicle_records():
        """获取车辆记录"""
        return VehicleRecordRepository.get_vehicle_records()
    
    @staticmethod
    def get_active_vehicle_record(plate_number: str):
        """获取指定车牌号的活跃车辆记录"""
        return VehicleRecordRepository.get_active_vehicle_record(plate_number)
    
    @staticmethod
    def get_vehicle_records_by_plate(plate_number: str, limit: int = 10):
        """获取指定车牌号的历史记录"""
        return VehicleRecordRepository.get_vehicle_records_by_plate(plate_number, limit)

class IncomeService:
    """收入服务"""
    
    @staticmethod
    def get_income_records():
        """获取收入记录"""
        return IncomeRepository.get_income_records()
    
    @staticmethod
    def get_income_record(record_id: int):
        """获取单条收入记录"""
        return IncomeRepository.get_income_record(record_id)
    
    @staticmethod
    def get_total_income():
        """获取总收入"""
        return IncomeRepository.get_total_income()
    
    @staticmethod
    def get_unpaid_bills(plate_number: str):
        """获取车牌号对应的未支付账单"""
        return IncomeRepository.get_unpaid_bills(plate_number)
    
    @staticmethod
    def get_all_unpaid_bills():
        """获取所有未支付账单"""
        return IncomeRepository.get_all_unpaid_bills()
    
    @staticmethod
    def process_payment(record_id: int, payment_method: str = "wechat"):
        """处理支付"""
        timestamp = int(time.time() * 1000)
        
        # 检查账单是否存在
        record = IncomeRepository.get_income_record(record_id)
        if not record:
            return {"success": False, "message": "账单不存在"}
        
        # 检查是否已支付
        if record.get("paid", False):
            return {"success": False, "message": "账单已支付"}
        
        # 获取关联的预约ID
        reservation_id = record.get("reservation_id")
        
        # 模拟支付过程
        payment_id = f"PAY{timestamp}{record_id}"
        result = IncomeRepository.update_payment_status(record_id, True, payment_method, payment_id, timestamp)
        
        if result:
            # 如果有关联的预约且大于0，更新预约状态为已完单
            if reservation_id and reservation_id > 0:
                # 获取预约信息
                reservation = ReservationRepository.get_reservation(reservation_id)
                if reservation and reservation["status"] == "waiting_payment":
                    # 更新预约状态为已完单
                    logger.info(f"支付成功，更新预约 {reservation_id} 状态为已完单")
                    ReservationRepository.update_reservation_status(reservation_id, "completed")
            
            return {
                "success": True,
                "message": "支付成功",
                "payment_id": payment_id,
                "payment_time": timestamp
            }
        else:
            return {"success": False, "message": "支付处理失败"}

class PricingService:
    """计费服务"""
    
    @staticmethod
    def calculate_fee(start_time: int, end_time: int):
        """计算费用"""
        # 获取活跃的计费规则
        rule = PricingRuleRepository.get_active_pricing_rule()
        
        if not rule:
            # 默认规则
            free_duration = 300  # 5分钟，单位秒
            unit_duration = 3600  # 1小时，单位秒
            unit_price = 5  # 5元
        else:
            free_duration = rule["free_duration"]
            unit_duration = rule["unit_duration"]
            unit_price = rule["unit_price"]
        
        # 计算停车时长（秒）
        duration_ms = end_time - start_time
        duration_seconds = duration_ms / 1000
        
        # 如果在免费时长内，不收费
        if duration_seconds <= free_duration:
            return 0
        
        # 超过免费时长，按单位时长计费
        billable_seconds = duration_seconds - free_duration
        units = (billable_seconds + unit_duration - 1) / unit_duration  # 向上取整
        
        # 计算费用
        fee = units * unit_price
        
        return fee

class PricingRuleService:
    """计费规则服务"""
    
    @staticmethod
    def get_pricing_rules():
        """获取所有计费规则"""
        return PricingRuleRepository.get_pricing_rules()
    
    @staticmethod
    def get_active_pricing_rule():
        """获取活跃的计费规则"""
        return PricingRuleRepository.get_active_pricing_rule()
    
    @staticmethod
    def create_pricing_rule(name: str, free_duration: int, unit_duration: int, unit_price: float, is_active: bool = False):
        """创建计费规则"""
        return PricingRuleRepository.create_pricing_rule(
            name,
            free_duration,
            unit_duration,
            unit_price,
            is_active
        )
    
    @staticmethod
    def update_pricing_rule(rule_id: int, name: str, free_duration: int, unit_duration: int, unit_price: float, is_active: bool = False):
        """更新计费规则"""
        return PricingRuleRepository.update_pricing_rule(
            rule_id,
            name,
            free_duration,
            unit_duration,
            unit_price,
            is_active
        )
    
    @staticmethod
    def activate_pricing_rule(rule_id: int):
        """激活计费规则"""
        return PricingRuleRepository.activate_pricing_rule(rule_id)

class DashboardService:
    """仪表盘服务"""
    
    @staticmethod
    def get_dashboard_data():
        """获取仪表盘数据"""
        # 获取车位使用情况汇总
        parking_summary = ParkingSpotRepository.get_parking_summary()
        
        # 获取待处理预约数量
        reservation_count = ReservationRepository.get_reservation_count()
        
        # 获取总收入
        total_income = IncomeRepository.get_total_income()
        
        # 获取最近的车辆记录
        recent_records = VehicleRecordRepository.get_vehicle_records()[:5]
        
        # 获取最近的车牌识别记录
        recent_detections = PlateDetectionRepository.get_plate_detections(10)
        
        return {
            "parking_summary": parking_summary,
            "reservation_count": reservation_count,
            "total_income": total_income,
            "recent_records": recent_records,
            "recent_detections": recent_detections
        } 